Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


meshchatx/src/backend/recovery/crash_recovery.py massive-changes (a914d68e) Text, 11.37 KB

Tff7b72import T7ee787os
Tff7b72import T7ee787platform
Tff7b72import T7ee787shutil
Tff7b72import T7ee787sqlite3
Tff7b72import T7ee787sys
Tff7b72import T7ee787traceback

Tff7b72import T7ee787psutil
Tff7b72import T7ee787RNS


Tff7b72class T56d364CrashRecoveryTb4b4b4:
T8b949e"""A diagnostic utility that intercepts application crashes and provides
meaningful error reports and system state analysis.
"""

Tff7b72def Tff7b72__init__Tb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3storage_dirTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3database_pathTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3public_dirTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3reticulum_config_dirTff7b72=Tff7b72NoneTb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstorage_dir Tff7b72= Te6edf3storage_dir
Tff7b72selfTff7b72.Td2a8ffdatabase_path Tff7b72= Te6edf3database_path
Tff7b72selfTff7b72.Td2a8ffpublic_dir Tff7b72= Te6edf3public_dir
Tff7b72selfTff7b72.Td2a8ffreticulum_config_dir Tff7b72= Te6edf3reticulum_config_dir
Tff7b72selfTff7b72.Td2a8ffenabled Tff7b72= Tff7b72True

T8b949e# Check environment variable to allow disabling the recovery system
Te6edf3env_val Tff7b72= Te6edf3osTff7b72.Td2a8ffenvironTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffMESHCHAT_NO_CRASH_RECOVERYTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3env_val Tff7b72in Tb4b4b4(Ta5d6ff"Ta5d6fftrueTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff1Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffyesTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffonTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffenabled Tff7b72= Tff7b72False

Tff7b72def Td2a8ffinstallTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Installs the crash recovery exception hook into the system."""
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffenabledTb4b4b4:
Tff7b72return

Te6edf3sysTff7b72.Td2a8ffexcepthook Tff7b72= Tff7b72selfTff7b72.Td2a8ffhandle_exception

Tff7b72def Td2a8ffdisableTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Disables the crash recovery system manually."""
Tff7b72selfTff7b72.Td2a8ffenabled Tff7b72= Tff7b72False

Tff7b72def Td2a8ffupdate_pathsTb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3storage_dirTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3database_pathTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3public_dirTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3reticulum_config_dirTff7b72=Tff7b72NoneTb4b4b4,
Tb4b4b4)Tb4b4b4:
T8b949e"""Updates the internal paths used for system diagnosis."""
Tff7b72if Te6edf3storage_dirTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstorage_dir Tff7b72= Te6edf3storage_dir
Tff7b72if Te6edf3database_pathTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffdatabase_path Tff7b72= Te6edf3database_path
Tff7b72if Te6edf3public_dirTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffpublic_dir Tff7b72= Te6edf3public_dir
Tff7b72if Te6edf3reticulum_config_dirTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffreticulum_config_dir Tff7b72= Te6edf3reticulum_config_dir

Tff7b72def Td2a8ffhandle_exceptionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3exc_typeTb4b4b4, Te6edf3exc_valueTb4b4b4, Te6edf3exc_tracebackTb4b4b4)Tb4b4b4:
T8b949e"""Intercepts unhandled exceptions to provide a detailed diagnosis report."""
T8b949e# Let keyboard interrupts pass through normally
Tff7b72if Tffa657issubclassTb4b4b4(Te6edf3exc_typeTb4b4b4, Tf85149KeyboardInterruptTb4b4b4)Tb4b4b4:
Te6edf3sysTff7b72.Td2a8ff__excepthook__Tb4b4b4(Te6edf3exc_typeTb4b4b4, Te6edf3exc_valueTb4b4b4, Te6edf3exc_tracebackTb4b4b4)
Tff7b72return

T8b949e# Use stderr for everything to ensure correct ordering in logs and console
Te6edf3out Tff7b72= Te6edf3sysTff7b72.Td2a8ffstderr

T8b949e# Print visual separator
Te6edf3outTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ff" Tff7b72+ Ta5d6ff"Ta5d6ff=Ta5d6ff" Tff7b72* T79c0ff70 Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4)
Te6edf3outTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff!!! APPLICATION CRASH DETECTED !!!Tffea00\nTa5d6ff"Tb4b4b4)
Te6edf3outTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff=Ta5d6ff" Tff7b72* T79c0ff70 Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4)

Te6edf3outTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ffError Summary:Tffea00\nTa5d6ff"Tb4b4b4)
Te6edf3outTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff Type: Tffd700{Te6edf3exc_typeTff7b72.Td2a8ff__name__Tffd700}Tffea00\nTa5d6ff"Tb4b4b4)
Te6edf3outTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff Message: Tffd700{Te6edf3exc_valueTffd700}Tffea00\nTa5d6ff"Tb4b4b4)

Te6edf3outTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ffSystem Environment Diagnosis:Tffea00\nTa5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffrun_diagnosisTb4b4b4(Te6edf3fileTff7b72=Te6edf3outTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3outTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff [ERROR] Failed to complete diagnosis: Tffd700{Te6edf3eTffd700}Tffea00\nTa5d6ff"Tb4b4b4)

Te6edf3outTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ffTechnical Traceback:Tffea00\nTa5d6ff"Tb4b4b4)
Te6edf3tracebackTff7b72.Td2a8ffprint_exceptionTb4b4b4(Te6edf3exc_typeTb4b4b4, Te6edf3exc_valueTb4b4b4, Te6edf3exc_tracebackTb4b4b4, Te6edf3fileTff7b72=Te6edf3outTb4b4b4)

Te6edf3outTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ff" Tff7b72+ Ta5d6ff"Ta5d6ff=Ta5d6ff" Tff7b72* T79c0ff70 Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4)
Te6edf3outTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ffRecovery Suggestions:Tffea00\nTa5d6ff"Tb4b4b4)
Te6edf3outTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff 1. Review the Ta5d6ff'Ta5d6ffSystem Environment DiagnosisTa5d6ff'Ta5d6ff section above.Tffea00\nTa5d6ff"Tb4b4b4)
Te6edf3outTff7b72.Td2a8ffwriteTb4b4b4(
Ta5d6ff"Ta5d6ff 2. Verify that all dependencies are installed (poetry install or pip install -r requirements.txt).Tffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3outTff7b72.Td2a8ffwriteTb4b4b4(
Ta5d6ff"Ta5d6ff 3. If database corruption is suspected, try starting with --auto-recover.Tffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3outTff7b72.Td2a8ffwriteTb4b4b4(
Ta5d6ff"Ta5d6ff 4. If the issue persists, report it to Ivan over another LXMF client: 7cc8d66b4f6a0e0e49d34af7f6077b5aTffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3outTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff=Ta5d6ff" Tff7b72* T79c0ff70 Tff7b72+ Ta5d6ff"Tffea00\nTffea00\nTa5d6ff"Tb4b4b4)
Te6edf3outTff7b72.Td2a8ffflushTb4b4b4(Tb4b4b4)

T8b949e# Exit with error code
Te6edf3sysTff7b72.Td2a8ffexitTb4b4b4(T79c0ff1Tb4b4b4)

Tff7b72def Td2a8ffrun_diagnosisTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3fileTff7b72=Te6edf3sysTff7b72.Td2a8ffstderrTb4b4b4)Tb4b4b4:
T8b949e"""Performs a series of OS-agnostic checks on the application's environment."""
T8b949e# Basic System Info
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ff- OS: Tffd700{Te6edf3platformTff7b72.Td2a8ffsystemTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff Tffd700{Te6edf3platformTff7b72.Td2a8ffreleaseTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff (Tffd700{Te6edf3platformTff7b72.Td2a8ffmachineTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff)Tffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff- Python: Tffd700{Te6edf3sysTff7b72.Td2a8ffversionTff7b72.Td2a8ffsplitTb4b4b4(Tb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4]Tffd700}Tffea00\nTa5d6ff"Tb4b4b4)

T8b949e# Resource Monitoring
Tff7b72tryTb4b4b4:
Te6edf3mem Tff7b72= Te6edf3psutilTff7b72.Td2a8ffvirtual_memoryTb4b4b4(Tb4b4b4)
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ff- Memory: Tffd700{Te6edf3memTff7b72.Td2a8ffpercentTffd700}Ta5d6ff% used (Tffd700{Te6edf3memTff7b72.Td2a8ffavailable Tff7b72/ Tb4b4b4(T79c0ff1024Tff7b72*Tff7b72*T79c0ff2Tb4b4b4)Tffd700:Ta5d6ff.1fTffd700}Ta5d6ff MB available)Tffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3memTff7b72.Td2a8ffpercent Tff7b72> T79c0ff95Tb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff [CRITICAL] System memory is dangerously low!Tffea00\nTa5d6ff"Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass

T8b949e# Filesystem Status
Tff7b72if Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff- Storage Path: Tffd700{Tff7b72selfTff7b72.Td2a8ffstorage_dirTffd700}Tffea00\nTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4)Tb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(
Ta5d6ff"Ta5d6ff [ERROR] Storage path does not exist. Check MESHCHAT_STORAGE_DIR.Tffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffaccessTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4, Te6edf3osTff7b72.Td2a8ffW_OKTb4b4b4)Tb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(
Ta5d6ff"Ta5d6ff [ERROR] Storage path is NOT writable. Check filesystem permissions.Tffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4)

Tff7b72tryTb4b4b4:
Te6edf3usage Tff7b72= Te6edf3shutilTff7b72.Td2a8ffdisk_usageTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4)
Te6edf3free_mb Tff7b72= Te6edf3usageTff7b72.Td2a8fffree Tff7b72/ Tb4b4b4(T79c0ff1024Tff7b72*Tff7b72*T79c0ff2Tb4b4b4)
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff - Disk Space: Tffd700{Te6edf3free_mbTffd700:Ta5d6ff.1fTffd700}Ta5d6ff MB freeTffea00\nTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3free_mb Tff7b72< T79c0ff50Tb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(
Ta5d6ff"Ta5d6ff [CRITICAL] Disk space is critically low (< 50MB)!Tffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass

T8b949e# Database Integrity
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdatabase_pathTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff- Database: Tffd700{Tff7b72selfTff7b72.Td2a8ffdatabase_pathTffd700}Tffea00\nTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdatabase_pathTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffgetsizeTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdatabase_pathTb4b4b4) Tff7b72== T79c0ff0Tb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(
Ta5d6ff"Ta5d6ff [WARNING] Database file exists but is empty (0 bytes).Tffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72tryTb4b4b4:
T8b949e# Open in read-only mode for safety during crash handling
Te6edf3conn Tff7b72= Te6edf3sqlite3Tff7b72.Td2a8ffconnectTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6fffile:Tffd700{Tff7b72selfTff7b72.Td2a8ffdatabase_pathTffd700}Ta5d6ff?mode=roTa5d6ff"Tb4b4b4,
Te6edf3uriTff7b72=Tff7b72TrueTb4b4b4,
Tb4b4b4)
Te6edf3cursor Tff7b72= Te6edf3connTff7b72.Td2a8ffcursorTb4b4b4(Tb4b4b4)
Te6edf3cursorTff7b72.Td2a8ffexecuteTb4b4b4(Ta5d6ff"Ta5d6ffPRAGMA integrity_checkTa5d6ff"Tb4b4b4)
Te6edf3res Tff7b72= Te6edf3cursorTff7b72.Td2a8fffetchoneTb4b4b4(Tb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72if Te6edf3res Tff7b72!= Ta5d6ff"Ta5d6ffokTa5d6ff"Tb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ff [ERROR] Database corruption detected: Tffd700{Te6edf3resTffd700}Tffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff - Integrity: OKTffea00\nTa5d6ff"Tb4b4b4)
Te6edf3connTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72except Te6edf3sqlite3Tff7b72.Td2a8ffDatabaseError Tff7b72as Te6edf3eTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ff [ERROR] Database is unreadable or not a SQLite file: Tffd700{Te6edf3eTffd700}Tffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff [ERROR] Database check failed: Tffd700{Te6edf3eTffd700}Tffea00\nTa5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff - Database: File not yet createdTffea00\nTa5d6ff"Tb4b4b4)

T8b949e# Frontend Assets
Tff7b72if Tff7b72selfTff7b72.Td2a8ffpublic_dirTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff- Frontend Assets: Tffd700{Tff7b72selfTff7b72.Td2a8ffpublic_dirTffd700}Tffea00\nTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpublic_dirTb4b4b4)Tb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(
Ta5d6ff"Ta5d6ff [ERROR] Frontend directory is missing. Web interface will fail to load.Tffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3index_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpublic_dirTb4b4b4, Ta5d6ff"Ta5d6ffindex.htmlTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3index_pathTb4b4b4)Tb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(
Ta5d6ff"Ta5d6ff [ERROR] index.html not found in frontend directory!Tffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff - Frontend Status: Assets verifiedTffea00\nTa5d6ff"Tb4b4b4)

T8b949e# Reticulum Status
Tff7b72selfTff7b72.Td2a8ffrun_reticulum_diagnosisTb4b4b4(Te6edf3fileTff7b72=Te6edf3fileTb4b4b4)

Tff7b72def Td2a8ffrun_reticulum_diagnosisTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3fileTff7b72=Te6edf3sysTff7b72.Td2a8ffstderrTb4b4b4)Tb4b4b4:
T8b949e"""Diagnoses the Reticulum Network Stack environment."""
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff- Reticulum Network Stack:Tffea00\nTa5d6ff"Tb4b4b4)

T8b949e# Check config directory
Te6edf3config_dir Tff7b72= Tff7b72selfTff7b72.Td2a8ffreticulum_config_dir Tff7b72or Te6edf3RNSTff7b72.Td2a8ffReticulumTff7b72.Td2a8ffconfigpath
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff - Config Directory: Tffd700{Te6edf3config_dirTffd700}Tffea00\nTa5d6ff"Tb4b4b4)

Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3config_dirTb4b4b4)Tb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff [ERROR] Reticulum config directory does not exist.Tffea00\nTa5d6ff"Tb4b4b4)
Tff7b72return

Te6edf3config_file Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3config_dirTb4b4b4, Ta5d6ff"Ta5d6ffconfigTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3config_fileTb4b4b4)Tb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff [ERROR] Reticulum config file is missing.Tffea00\nTa5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72tryTb4b4b4:
T8b949e# Basic config validation
Tff7b72with Tffa657openTb4b4b4(Te6edf3config_fileTb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3content Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72if Ta5d6ff"Ta5d6ff[reticulum]Ta5d6ff" Tff7b72not Tff7b72in Te6edf3contentTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(
Ta5d6ff"Ta5d6ff [ERROR] Reticulum config file is invalid (missing [reticulum] section).Tffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff - Config File: OKTffea00\nTa5d6ff"Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff [ERROR] Could not read Reticulum config: Tffd700{Te6edf3eTffd700}Tffea00\nTa5d6ff"Tb4b4b4)

T8b949e# Extract recent RNS log entries if possible
T8b949e# Check common log file locations
Te6edf3log_paths Tff7b72= Tb4b4b4[
Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3config_dirTb4b4b4, Ta5d6ff"Ta5d6fflogfileTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3config_dirTb4b4b4, Ta5d6ff"Ta5d6ffrnsd.logTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ff/var/log/rnsd.logTa5d6ff"Tb4b4b4,
Tb4b4b4]

Te6edf3found_logs Tff7b72= Tff7b72False
Tff7b72for Te6edf3logfile Tff7b72in Te6edf3log_pathsTb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3logfileTb4b4b4)Tb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff - Recent Log Entries (Tffd700{Te6edf3logfileTffd700}Ta5d6ff):Tffea00\nTa5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3logfileTb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3lines Tff7b72= Te6edf3fTff7b72.Td2a8ffreadlinesTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3linesTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff (Log file is empty)Tffea00\nTa5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72for Te6edf3line Tff7b72in Te6edf3linesTb4b4b4[Tff7b72-T79c0ff15Tb4b4b4:Tb4b4b4]Tb4b4b4:
Tff7b72if Ta5d6ff"Ta5d6ffERRORTa5d6ff" Tff7b72in Te6edf3line Tff7b72or Ta5d6ff"Ta5d6ffCRITICALTa5d6ff" Tff7b72in Te6edf3lineTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff > [ALERT] Tffd700{Te6edf3lineTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tffd700}Tffea00\nTa5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff > Tffd700{Te6edf3lineTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tffd700}Tffea00\nTa5d6ff"Tb4b4b4)
Te6edf3found_logs Tff7b72= Tff7b72True
Tff7b72break T8b949e# Stop at first found log file
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff [ERROR] Could not read logfile: Tffd700{Te6edf3eTffd700}Tffea00\nTa5d6ff"Tb4b4b4)

Tff7b72if Tff7b72not Te6edf3found_logsTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff - Logs: No RNS log files found in standard locations.Tffea00\nTa5d6ff"Tb4b4b4)

T8b949e# Check for interfaces and transport status
Tff7b72tryTb4b4b4:
T8b949e# Try to get more info from RNS if it's already running
Tff7b72if Tffa657hasattrTb4b4b4(Te6edf3RNSTff7b72.Td2a8ffTransportTb4b4b4, Ta5d6ff"Ta5d6ffinterfacesTa5d6ff"Tb4b4b4) Tff7b72and Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffinterfacesTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff - Active Interfaces: Tffd700{Tffa657lenTb4b4b4(Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffinterfacesTb4b4b4)Tffd700}Tffea00\nTa5d6ff"Tb4b4b4)
Tff7b72for Te6edf3iface Tff7b72in Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffinterfacesTb4b4b4:
Te6edf3status Tff7b72= Ta5d6ff"Ta5d6ffActiveTa5d6ff" Tff7b72if Te6edf3ifaceTff7b72.Td2a8ffonline Tff7b72else Ta5d6ff"Ta5d6ffOfflineTa5d6ff"
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff > Tffd700{Te6edf3ifaceTffd700}Ta5d6ff [Tffd700{Te6edf3statusTffd700}Ta5d6ff]Tffea00\nTa5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(
Ta5d6ff"Ta5d6ff - Active Interfaces: None registered (Reticulum may not be initialized yet)Tffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass

T8b949e# Check for common port conflicts
Te6edf3common_ports Tff7b72= Tb4b4b4[T79c0ff4242Tb4b4b4, T79c0ff8000Tb4b4b4, T79c0ff8080Tb4b4b4] T8b949e# Reticulum default is often 4242
Tff7b72for Te6edf3port Tff7b72in Te6edf3common_portsTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72for Te6edf3conn Tff7b72in Te6edf3psutilTff7b72.Td2a8ffnet_connectionsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3connTff7b72.Td2a8ffladdrTff7b72.Td2a8ffport Tff7b72== Te6edf3port Tff7b72and Te6edf3connTff7b72.Td2a8ffstatus Tff7b72== Ta5d6ff"Ta5d6ffLISTENTa5d6ff"Tb4b4b4:
Te6edf3fileTff7b72.Td2a8ffwriteTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ff [ALERT] Port Tffd700{Te6edf3portTffd700}Ta5d6ff is already in use by PID Tffd700{Te6edf3connTff7b72.Td2a8ffpidTffd700}Ta5d6ff. Potential conflict.Tffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────